package com.boast.workflow;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.opensymphony.workflow.FactoryException;
import com.opensymphony.workflow.loader.AbstractWorkflowFactory;
import com.opensymphony.workflow.loader.WorkflowDescriptor;
import com.opensymphony.workflow.loader.WorkflowLoader;
import com.zhangyj.cache.CacheEngine;
import com.zhangyj.cache.DataCacheManager;
import com.zhangyj.db.DBUtil;

public class JDBCWorkflowFactory extends AbstractWorkflowFactory implements Serializable {
	private static final long serialVersionUID = 1798995150924753204L;
	private static final CacheEngine cache = DataCacheManager.getCacheEngine();
	private static final String CACHE_KEY = "workflow";
	// ~ Instance fields
	// ////////////////////////////////////////////////////////

	// protected Map workflows;
	protected boolean useCache;

	// ~ Methods
	// ////////////////////////////////////////////////////////////////

	public void setLayout(String workflowName, Object layout) {
	}

	public Object getLayout(String workflowName) {
		return null;
	}

	public boolean isModifiable(String name) {
		return false;
	}

	public String getName() {
		return "";
	}

	public WorkflowDescriptor getWorkflow(String name, boolean validate) throws FactoryException {
		WorkflowDescriptor c = (WorkflowDescriptor) cache.getObject(CACHE_KEY, name);
		if (c == null) {
			c = loadWorkflowConfig(name);
		}
		return c;
	}

	private WorkflowDescriptor loadWorkflowConfig(String name) throws FactoryException {
		InputStream in = null;
		try {
			String result = DBUtil.getClob("SELECT entity FROM workflowinfo where isdel=0 and WFNAME =? ", name, DBUtil.DATATYPE_STRING);
			in = new ByteArrayInputStream(result.getBytes("utf-8"));
			
			WorkflowDescriptor descriptor = WorkflowLoader.load(in, true);
			
			if (useCache) {
				cache.putObject(CACHE_KEY, name, descriptor);
			}
			return descriptor;
		} catch (Exception e) {
			throw new FactoryException(e);
		}
	}

	private synchronized String[] loadWorkflowNames() {
		Connection conn = null;
		try {
			List<String> list = new ArrayList<String>();
			conn = DBUtil.getConnection();
			PreparedStatement ps = conn.prepareStatement("select wfname from workflowinfo where isdel=0 ");
			ResultSet rst = ps.executeQuery();
			while (rst.next()) {
				list.add(rst.getString(1));
			}
			String[] arr = list.toArray(new String[list.size()]);
			if (useCache) {
				cache.putObject(CACHE_KEY, "_workflownames", arr);
			}
			return arr;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return null;
		// throw new FactoryException("Unknown workflow name \"" + name + '\"');
	}

	public String[] getWorkflowNames() {
		String[] res = (String[]) cache.getObject(CACHE_KEY, "_workflownames");
		if (res == null) {
			res = loadWorkflowNames();
		}
		return res;
	}

	public void createWorkflow(String name) {
	}

	public void initDone() throws FactoryException {
		useCache = getProperties().getProperty("cache", "false").equals("true");
	}

	public boolean removeWorkflow(String name) throws FactoryException {
		throw new FactoryException("remove workflow not supported");
	}

	public void renameWorkflow(String oldName, String newName) {
	}

	public void save() {
	}

	public boolean saveWorkflow(String name, WorkflowDescriptor descriptor, boolean replace) throws FactoryException {
		throw new FactoryException("save workflow not supported");
	}

	// ~ Inner Classes
	// //////////////////////////////////////////////////////////
}
